# coding: utf-8
import signal
import threading
import time

import os
import pandas as pd
import sys

from multiprocessing import Queue, Process
from pandas import Timestamp

from fbprophet import Prophet


def prophet_run():
    weekly_seasonality = False
    yearly_seasonality = True
    daily_seasonality = False
    holidays = None
    growth = 'linear'

    m = Prophet(weekly_seasonality=weekly_seasonality,
                yearly_seasonality=yearly_seasonality,
                daily_seasonality=daily_seasonality,
                holidays=holidays,
                growth=growth)

    a = [[Timestamp('2016-03-07 00:00:00'), 100, 4225.0, 0],
         [Timestamp('2016-03-14 00:00:00'), 100, 4225.0, 0],
         [Timestamp('2016-03-21 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-03-28 00:00:00'), 2200, 4225.0, 0],
         [Timestamp('2016-04-04 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-04-11 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-04-18 00:00:00'), 50, 4225.0, 0],
         [Timestamp('2016-04-25 00:00:00'), 300, 4225.0, 0],
         [Timestamp('2016-05-02 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-05-09 00:00:00'), 100, 4225.0, 0],
         [Timestamp('2016-05-16 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-05-23 00:00:00'), 150, 4225.0, 0],
         [Timestamp('2016-05-30 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-06-06 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-06-13 00:00:00'), 100, 4225.0, 0],
         [Timestamp('2016-06-20 00:00:00'), 100, 4225.0, 0],
         [Timestamp('2016-06-27 00:00:00'), 100, 4225.0, 0],
         [Timestamp('2016-07-04 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-07-11 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-07-18 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-07-25 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-08-01 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-08-08 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-08-15 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-08-22 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-08-29 00:00:00'), 2360, 4225.0, 0],
         [Timestamp('2016-09-05 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-09-12 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-09-19 00:00:00'), 50, 4225.0, 0],
         [Timestamp('2016-09-26 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-10-03 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-10-10 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-10-17 00:00:00'), 1000, 4225.0, 0],
         [Timestamp('2016-10-24 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-10-31 00:00:00'), 50, 4225.0, 0],
         [Timestamp('2016-11-07 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-11-14 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-11-21 00:00:00'), 1100, 4225.0, 0],
         [Timestamp('2016-11-28 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-12-05 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-12-12 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-12-19 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2016-12-26 00:00:00'), 3000, 4225.0, 0],
         [Timestamp('2017-01-02 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-01-09 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-01-16 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-01-23 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-01-30 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-02-06 00:00:00'), 2500, 4225.0, 0],
         [Timestamp('2017-02-13 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-02-20 00:00:00'), 1500, 4225.0, 0],
         [Timestamp('2017-02-27 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-03-06 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-03-13 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-03-20 00:00:00'), 2500, 4225.0, 0],
         [Timestamp('2017-03-27 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-04-03 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-04-10 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-04-17 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-04-24 00:00:00'), 3250, 4225.0, 0],
         [Timestamp('2017-05-01 00:00:00'), 0, 4225.0, 0],
         [Timestamp('2017-05-08 00:00:00'), 0, 4225.0, 0]]
    df = pd.DataFrame(a)
    df = df.rename(columns={0: 'ds',  # 实际的列名为数字，而不是字符串
                            1: 'y',  # 使用 '0': 'uid'来改列名是改不了的
                            2: 'cap',
                            3: 'floor'})
    print(df)
    m.fit(df)


class Job(threading.Thread):

    def __init__(self, *args, **kwargs):
        super(Job, self).__init__(*args, **kwargs)
        self.__flag = threading.Event()  # 用于暂停线程的标识
        self.__flag.set()  # 设置为True
        self.__running = threading.Event()  # 用于停止线程的标识
        self.__running.set()  # 将running设置为True

    def run(self):
        # while self.__running.isSet():
        #     self.__flag.wait()      # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回
        #     print(time.time())
        #     time.sleep(1)
        prophet_run()

    def pause(self):
        self.__flag.clear()  # 设置为False, 让线程阻塞

    def resume(self):
        self.__flag.set()  # 设置为True, 让线程停止阻塞

    def stop(self):
        self.__flag.set()  # 将线程从暂停状态恢复, 如何已经暂停的话
        self.__running.clear()  # 设置为False


class Watcher:
    """this class solves two problems with multithreaded
    programs in Python, (1) a signal might be delivered
    to any thread (which is just a malfeature) and (2) if
    the thread that gets the signal is waiting, the signal
    is ignored (which is a bug).

    The watcher is a concurrent process (not thread) that
    waits for a signal and the process that contains the
    threads.  See Appendix A of The Little Book of Semaphores.
    http://greenteapress.com/semaphores/

    I have only tested this on Linux.  I would expect it to
    work on the Macintosh and not work on Windows.
    """

    def __init__(self):
        """ Creates a child thread, which returns.  The parent
            thread waits for a KeyboardInterrupt and then kills
            the child thread.
        """
        self.handle_one = None
        self.child = os.fork()
        if self.child == 0:
            # this is child process
            return
        else:
            # this is father process
            self.watch()

    def watch(self):
        # try:
        #     os.wait()
        # except KeyboardInterrupt:
        #     print('KeyBoardInterrupt')
        #     self.kill()
        # sys.exit()

        # new one
        for i in range(5):
            print("in watcher:", i)
            time.sleep(1)
        if self.handle_one is not None:
            self.handle_one.stop()

        self.kill()
        sys.exit()

    def kill(self):
        try:
            os.kill(self.child, signal.SIGKILL)
        except OSError:  # , ex:
            pass
            # print("kill error")
            # print(ex)


w1 = Watcher()

aa = Job()
aa.setDaemon(True)
w1.handle_one = aa
aa.start()
# time.sleep(3)
# aa.pause()
time.sleep(5)
# aa.resume()
# time.sleep(3)
# aa.pause()
# time.sleep(2)
aa.stop()
print("end of line")
exit(0)


# def watcher_2(msg_in):
#     for ii in range(9):
#         print(ii, msg_in)
#         time.sleep(1)


# pool = multiprocessing.Pool(processes=3)
# for i in range(4):
#     msg = "hello %d" % i
#     pool.apply_async(watcher_2, (msg,))  # 维持执行的进程总数为processes，当一个进程执行完毕后会添加新的进程进去
#
# print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
# pool.close()
# pool.join()  # 调用join之前，先调用close函数，否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
# print("Sub-process(es) done.")

def f(q, n):
    q.put([n, 'hello'])


# 此queue不是直接导入的import Queue,这个是multiprocessing重新封装的
q = Queue()
# 循环6个进程
for i in range(5):
    p = Process(target=f, args=(q, i))
    p.start()

# 等待子进程完毕后在继续执行
p.join()
for i in range(q.qsize()):
    print(q.get())
